/*
 * Creado por NIN
 * User: sebastian.lucas
 * Date: 19/04/2007
 * Time: 9:23
 */

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

namespace CSE
{
	/// <summary>
	/// Description of Stage.
	/// </summary>
	public class Stage
	{
	    /*
	     * Constants
	     */
	    public static readonly int GRID_SIZE = 32;
	    public static readonly int SHIFT_ORIGIN = 8;
	    
	    /*
	     * Variables
	     */
	    public static Bitmap bmp = null;
	    public static Bitmap bmp_grid = null;
	    
	    public static int zoom = 1;
	    public static int ox = -1;
	    public static int oy = -1;
	    public static int preview_frame = -1;
	    
	    /*
	     * Init
	     */
	    public static void Init ()
	    {
	        if (bmp_grid != null)
	        {
	            return;
	        }
	        
	        bmp_grid = Utils.LoadBitmapResource("grid.Bitmap");
	        
	        if (bmp_grid == null)
	        {
	            Utils.Trace("NULL!");
	        }
	    }
	    
	    /*
	     * Shutdown
	     */
	    public static void Shutdown ()
	    {
	    }
	    
	    /*
		 * GetPixelsX
		 */
		public static int GetPixelsX (int x, int w)
		{
		    return Utils.GetViewportPixel(x, w, ox, zoom);
		}
		
		/*
		 * GetPixelsY
		 */
		public static int GetPixelsY (int y, int h)
		{
			return Utils.GetViewportPixel(y, h, oy, zoom);
		}
	    
	    /*
	     * =============================================================================================
	     * Draw Stuff
	     */
	    private static int lw = -1;
	    private static int lh = -1;
	    
	    /*
	     * DrawGrid
	     */
	    public static void DrawGrid (Graphics g, int w, int h)
	    {
	        int x=0, y=0, xs=w/GRID_SIZE, ys=h/GRID_SIZE;
	        
	        xs++;
	        ys++;
	        
	        for (y=0; y<ys; y++)
	        {
	            for (x=0; x<xs; x++)
	            {
	                g.DrawImage(bmp_grid, x*GRID_SIZE, y*GRID_SIZE);
	            }
	        }
	    }
	    
	    /*
	     * DrawAxes
	     */
	    public static void DrawAxes (Graphics g, int w, int h)
	    {
	    	Pen pen = new Pen(Preferences.grid_color, 1);
	    	
	    	g.DrawLine(pen, ox, 0, ox, h);
	        g.DrawLine(pen, 0, oy, w, oy);
	    }
	    
	    /*
	     * DrawBackground
	     */
	    public static void DrawBackground (Graphics g, int w, int h)
	    {
	        if (w != lw
            && h != lh)
	        {
	            int xs=((w/GRID_SIZE)/2)*GRID_SIZE, ys=((h/GRID_SIZE)/2)*GRID_SIZE;
	            bmp = null;
	            bmp = new Bitmap(w, h, PixelFormat.Format16bppRgb555);
	            Graphics m = Graphics.FromImage(bmp);
	            
	            ox = xs;
	    	    oy = ys;
	            
	            DrawGrid(m, w, h);
	            
	            lw = w;
	            lh = h;
	        }
	        
	        g.DrawImage(bmp, 0, 0);
	    }
	    
	    /*
	     * DrawSelectionBox
	     */
	    public static void DrawSelectionBox (Graphics g, Clip _clip)
	    {
	    	Pen p = new Pen(Preferences.sel_color, zoom);
	    	p.DashStyle = DashStyle.Dash;
	    	g.DrawRectangle(p, ox + (_clip.r.X*zoom), oy + (_clip.r.Y*zoom),
	    	                (_clip.r.Width-1)*zoom, (_clip.r.Height - 1)*zoom);
	    }
	    
	    /*
	     * DrawSourceImage
	     */
	    public static void DrawSourceImage (Graphics g)
	    {
	    	if (Workspace.bitmap == null
	    	|| MainForm.libEdit == null)
	    	{
	    		// TODO: let know the user this!
	    		return;
	    	}
	    	
	    	ImageAttributes attr = new ImageAttributes();
	    	Bitmap _bmp = Workspace.bitmap;
	    	Clip _clip = (Clip)MainForm.libEdit.Tag;
	    	
	    	attr.SetColorKey(_bmp.GetPixel(0, 0), _bmp.GetPixel(0, 0));
	    	
	    	if (_clip.type == Workspace.TYPE_CLIP
	    	&& _clip.usebitmap)
	    	{
    			Rectangle dstRect = new Rectangle(ox, oy, _bmp.Width*zoom, _bmp.Height*zoom);
    			g.DrawImage(_bmp,
    		            	dstRect,
    		            	0, 0,
    		            	_bmp.Width,
    		            	_bmp.Height,
							GraphicsUnit.Pixel,
							attr);
    			
    			DrawSelectionBox(g, _clip);
	    	}
	    	else if (_clip.type == Workspace.TYPE_CLIP)
	    	{
	    	    int i=0;
	    	    ClipChild cc = null;
	    	    Clip cc_clip = null;
	    	    
	    	    for (i=0; i<_clip.childs.Count; i++)
	    	    {
	    	        cc = _clip.childs[i];
	    	        cc_clip = Workspace.GetClipFromName(cc.name);
	    	        
	    	        if (cc_clip == null)
	    	        {
	    	            Utils.MsgBox("Clip \"" + cc.name + "\" doesn't exist!");
	    	            continue;
	    	        }
	    	        
                    if (cc_clip.usebitmap)
                    {
                        cc_clip.DrawBitmapClip(g, _bmp, attr, ox + (cc.x*zoom), oy + (cc.y*zoom), cc_clip.r.Width*zoom, cc_clip.r.Height*zoom);
                    }
                    else if (cc_clip.type == Workspace.TYPE_CLIP)
                    {
                        cc_clip.DrawStaticClip(g, _bmp, attr, ox + (cc.x*zoom), oy + (cc.y*zoom), zoom);
                    }
	    	    }
	    	    
	    	    DrawSelectionBox(g, _clip);
	    	}
	    	else if (_clip.type == Workspace.TYPE_ANIMCLIP)
	    	{
                int i=0;
	    	    ClipChild cc = null;
	    	    Clip cc_clip = null;
	    	    
	    	    for (i=0; i<_clip.childs.Count; i++)
	    	    {
	    	        if (MainForm.tl.guide_index != i)
	    	        {
	    	            continue;
	    	        }
	    	        
	    	        cc = _clip.childs[i];
	    	        cc_clip = Workspace.GetClipFromName(cc.name);
	    	        
	    	        if (cc_clip == null)
	    	        {
	    	            Utils.MsgBox("Clip \"" + cc.name + "\" doesn't exist!");
	    	            continue;
	    	        }
	    	        
                    if (cc_clip.usebitmap)
                    {
                        cc_clip.DrawBitmapClip(g, _bmp, attr, ox + (cc.x*zoom), oy + (cc.y*zoom), cc_clip.r.Width*zoom, cc_clip.r.Height*zoom);
                    }
                    else if (cc_clip.type == Workspace.TYPE_CLIP)
                    {
                        cc_clip.DrawStaticClip(g, _bmp, attr, ox + (cc.x*zoom), oy + (cc.y*zoom), zoom);
                    }
	    	    }
	    	}
	    	
	    	attr.Dispose();
	    }
	    
	    /*
	     * DrawPreview
	     */
	    public static void DrawPreview (Graphics g, int w, int h)
	    {
	        if (Workspace.type == Workspace.TYPE_NONE)
	        {
	            return;
	        }
	        
	        g.Clear(Color.FromArgb(255,0,0,0));
	        
	        DrawGrid(g, w, h);
	        
	        if (MainForm.libSel == null
	        || Workspace.bitmap == null
			|| MainForm.libSel.Tag == null)
	        {
	            return;
	        }
	        
	        ImageAttributes attr = new ImageAttributes();
	    	Bitmap _bmp = Workspace.bitmap;
	    	Clip _clip = (Clip)MainForm.libSel.Tag;
	    	int _w = (_clip.r.Width > w) ? w:_clip.r.Width;
	    	int _h = (_clip.r.Height > h) ? h:_clip.r.Height;
	    	
	    	attr.SetColorKey(_bmp.GetPixel(0, 0), _bmp.GetPixel(0, 0));
	        
	        if (_clip.type == Workspace.TYPE_CLIP
	    	&& _clip.usebitmap)
	    	{
	    	    Rectangle dstRect = new Rectangle((w >> 1) - (_w >> 1), (h >> 1) - (_h >> 1), _w, _h);
    			g.DrawImage(_bmp,
    		            	dstRect,
    		            	_clip.r.X, _clip.r.Y,
    		            	_clip.r.Width,
    		            	_clip.r.Height,
							GraphicsUnit.Pixel,
							attr);
	    	}
	    	else if (_clip.type == Workspace.TYPE_CLIP)
	    	{
	    		int i=0;
	    		Clip cc = null;
	    		
	    		for (i=0; i<_clip.childs.Count; i++)
	    		{
	    			cc = Workspace.GetClipFromName(_clip.childs[i].name);
	    			
	    			if (cc == null)
	    			{
	    				Utils.Trace(">> NULL MODULE! (" + _clip.childs[i].name + ")");
	    				continue;
	    			}
	    			
	    			if (cc.usebitmap)
	    			{
	    			    cc.DrawBitmapClip(g, _bmp, attr, (w >> 1) + _clip.childs[i].x, (h >> 1) + _clip.childs[i].y, cc.r.Width, cc.r.Height);
	    			}
	    			else if (cc.type == Workspace.TYPE_CLIP)
	    			{
	    				cc.DrawStaticClip(g, _bmp, attr, (w >> 1) + _clip.childs[i].x, (h >> 1) + _clip.childs[i].y, 1);
	    			}
	    		}
	    	}
	    	else if (_clip.type == Workspace.TYPE_ANIMCLIP)
	    	{
                int i=0;
	    	    ClipChild cc = null;
	    	    Clip cc_clip = null;
	    	    
	    	    if (preview_frame < 0
	    	    || preview_frame > _clip.childs.Count - 1)
	    	    {
	    	        preview_frame = 0;
	    	    }
	    	    else
	    	    {
	    	        preview_frame++;
	    	    }
	    	    
	    	    for (i=0; i<_clip.childs.Count; i++)
	    	    {
	    	        if (preview_frame != i)
	    	        {
	    	            continue;
	    	        }
	    	        
	    	        cc = _clip.childs[i];
	    	        cc_clip = Workspace.GetClipFromName(cc.name);
	    	        
	    	        if (cc_clip == null)
	    	        {
	    	            Utils.MsgBox("Clip \"" + cc.name + "\" doesn't exist!");
	    	            continue;
	    	        }
	    	        
                    if (cc_clip.usebitmap)
                    {
                        cc_clip.DrawBitmapClip(g, _bmp, attr, (w >> 1) + _clip.childs[i].x, (h >> 1) + _clip.childs[i].y, cc_clip.r.Width, cc_clip.r.Height);
                    }
                    else if (cc_clip.type == Workspace.TYPE_CLIP)
                    {
                        cc_clip.DrawStaticClip(g, _bmp, attr, (w >> 1) + _clip.childs[i].x, (h >> 1) + _clip.childs[i].y, 1);
                    }
	    	    }
	    	}
	    	
	    	attr.Dispose();
	    	
	    	g.Flush();
	    }
	    
	    /*
	     * Draw
	     */
	    public static void Draw (Graphics g, int w, int h)
	    {
	        if (Workspace.type == Workspace.TYPE_NONE)
	        {
	            return;
	        }
	        
	        if (g.InterpolationMode != InterpolationMode.NearestNeighbor)
	        {
	            g.InterpolationMode = InterpolationMode.NearestNeighbor;
	        }
	        
	        g.Clear(Color.FromArgb(255,0,0,0));
	        DrawBackground(g, w, h);
	        DrawAxes(g, w, h);
	        DrawSourceImage(g);
	        g.Flush();
	    }
	}
}
